package com.woniu.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu.entity.Manager;
import com.woniu.entity.ManagerRole;
import com.woniu.entity.User;
import com.woniu.model.Result;
import com.woniu.service.ManagerRoleService;
import com.woniu.service.ManagerService;
import com.woniu.service.UserService;
import com.woniu.service.util.FileUpload;
import com.woniu.service.util.JwtUtil;
import com.woniu.service.util.Md5Util;
import com.woniu.service.util.UserTokenUtil;
import com.woniu.util.MyUtil;

import com.woniu.util.SnowFlow;
import io.swagger.annotations.ApiOperation;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.StringRedisTemplate;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author D
 * @since 2023-03-27 08:24:57
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    ManagerService managerService;
    @Autowired
    private ManagerRoleService managerRoleService;
    @Autowired
    private UserService userService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    SnowFlow snowFlow = new SnowFlow();

    /**
     * 发送登录验证码
     *
     * @param phoneNumber 手机号码
     * @return 返回发送结果
     */
    @RequestMapping("/sendLoginCode")
    public Result<String> sendCode(String phoneNumber) {
        //生成验证码
        String code = MyUtil.randomNum(4);
        Map<String, String> infoMap = new HashMap<>();
        infoMap.put("phone", phoneNumber);
        infoMap.put("code", code);
        //发送短信息

        rabbitTemplate.convertAndSend("sendCodeExchange", "sendLoginCode", infoMap);
        //redis存储验证码5分钟有效期
        stringRedisTemplate.opsForValue().set(phoneNumber + "loginCode", code, 5, TimeUnit.MINUTES);
        return Result.successResult("短息发送成功");
    }

    /**
     * 用户登录
     *
     * @param phoneNumber 手机号码
     * @param password    密码
     * @param code        验证码
     * @param response    HTTP响应
     * @return 返回登录结果
     */
    @RequestMapping("/login")
    public Result<Map<String, String>> login(String phoneNumber, String password, String code, HttpServletResponse response, HttpServletRequest request) {
        User user = userService.getByPhoneNumber(phoneNumber);
        Map<String, String> map = new HashMap<>();
        //用户通过手机号密码登录
        if (password != null && !"".equals(password)) {
            if (user == null) {
                map.put("msg", "您还未注册！请先完成注册！");
                return Result.failResult("msg", map);
            } else if (!user.getPassword().equals(Md5Util.encode(password))) {
                map.put("msg", "密码错误！");
                return Result.failResult("msg", map);
            }
        // 用户通过手机号验证码登录
        } else {
            String isSame = stringRedisTemplate.opsForValue().get(phoneNumber + "loginCode");
            if (isSame == null) {
                map.put("msg", "验证码已失效！请重新发送");
                return Result.failResult("msg", map);
            }
            ;
            if (!isSame.equals(code)) {
                map.put("msg", "验证码输入错误！");
                return Result.failResult("msg", map);
            }
            ;
        }
        List<ManagerRole> managerRoleList = managerRoleService.list(new QueryWrapper<ManagerRole>().eq("manager_id", user.getUserCode()));
        String roleId = managerRoleList.stream().anyMatch(o -> o.getRoleId() == 9l) ? "9" : null;
        roleId = managerRoleList.stream().anyMatch(o -> o.getRoleId() == 11l) ? "11" : roleId;
        roleId = managerRoleList.stream().anyMatch(o -> o.getRoleId() == 12l) ? "12" : roleId;
        String token = UserTokenUtil.createUserToken(user.getUserCode().toString(), response, stringRedisTemplate);
        map.put("token", token);
        map.put("role", roleId);

        return Result.successResult(map);
    }

    @RequestMapping("/register")
    public Result<String> register(String phoneNumber, String registerCode) {
        String password = new String();
        if (userService.getByPhoneNumber(phoneNumber) != null) return Result.failResult("手机号已存在，请直接登录！");
        String validateCode = stringRedisTemplate.opsForValue().get(phoneNumber + "registerCode");
        if (validateCode == null || "".equals(validateCode)) return Result.failResult("验证码已失效，请重新发送！");
        if (!registerCode.equals(validateCode)) return Result.failResult("验证码错误！");
        String phoneLastFour = phoneNumber.substring(phoneNumber.length() - 4);
        //添加用户
        User user = new User();
        user.setUserCode(snowFlow.nextId());
        user.setPhoneNumber(phoneNumber);
        password = "Wn" + MyUtil.randomNum(4) + phoneLastFour;
        user.setPassword(Md5Util.encode(password));
        user.setTotalScore(0);
        user.setProfilePhoto("https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png");
        user.setUsername("蜗牛_" + phoneLastFour);
        userService.save(user);
        Manager manager = new Manager();
        manager.setId(snowFlow.nextId());
        manager.setLocked("");
        manager.setUserCode(user.getUserCode().toString());
        manager.setCellphone(phoneNumber);
        manager.setUserName("蜗牛_" + phoneLastFour);
        manager.setInsertTime(new Date());
        manager.setUpdateTime(new Date());
        manager.setUserPassword(Md5Util.encode(password));
        managerService.save(manager);
        //创建角色和用户关联 默认权限为学生
        ManagerRole managerRole = new ManagerRole();
        managerRole.setId(snowFlow.nextId());
        managerRole.setRoleId(12l);
        managerRole.setManagerId(user.getUserCode());
        managerRole.setInsertTime(new Date());
        managerRole.setUpdateTime(new Date());
        managerRoleService.save(managerRole);
        return Result.successResult(password);
    }

    /**
     * 发送注册验证码
     *
     * @param phoneNumber 手机号码
     * @return 返回成功或者失败的结果信息
     */
    @RequestMapping("/sendRegisterCode")
    public Result<String> sendRegisterCode(String phoneNumber) {
        //生成验证码
        String code = MyUtil.randomNum(4);
        Map<String, String> infoMap = new HashMap<>();
        infoMap.put("phone", phoneNumber);
        infoMap.put("code", code);
        //发送短信息
        rabbitTemplate.convertAndSend("sendCodeExchange", "sendRegisterCode", infoMap);
        //redis存储验证码5分钟有效期
        stringRedisTemplate.opsForValue().set(phoneNumber + "registerCode", code, 5, TimeUnit.MINUTES);
        return Result.successResult("短息发送成功");
    }

    /**
     * 退出登录
     *
     * @param request  Request对象
     * @param response Response对象
     * @return 返回成功信息
     */
    @RequestMapping("/logout")
    public Result<String> logout(HttpServletRequest request, HttpServletResponse response) {
        UserTokenUtil.deleteUserToken(response, request, stringRedisTemplate);
        return Result.successResult("ok");
    }

    /**
     * 获取当前用户信息
     *
     * @param token 用户token
     * @return 返回用户信息
     */
    @PostMapping("getCurrentAccount")
    public Result<User> getCurrentUserName(String token) throws Exception {
        if (token == null) {
            return Result.successResult(null);
        }
        Long userCode = Long.parseLong(JwtUtil.parseValueWithoutException(token, "token"));
        return Result.successResult(userService.getById(userCode));
    }

    /**
     * 上传头像
     *
     * @param file 上传的文件
     * @return 返回上传结果
     * @throws IOException 文件IO异常
     */
    @ApiOperation(value = "上传头像")
    @PostMapping("upload")
    public Result upload(MultipartFile file) {
        return Result.successResult(FileUpload.upload(file));
    }

    /**
     * 修改用户头像
     *
     * @param token 用户 token
     * @return 返回执行结果
     */
    @ApiOperation(value = "修改头像")
    @PostMapping("updateProfilePhoto")
    public Result updateProfilePhoto(String token, String fileName) {

        Long userCode = Long.valueOf(JwtUtil.parseValueWithoutException(token, "token"));
        User user = userService.getById(userCode);

        user.setProfilePhoto("http://192.168.201.41:8004/imgs/" + fileName);
        userService.updateById(user);
        return Result.successResult("ok");
    }

    /**
     * 修改密码和昵称
     *
     * @param token    用户token
     * @param username 用户昵称
     * @param password 用户密码
     * @return 返回操作结果
     * @throws IOException 输入输出异常
     */
    @ApiOperation(value = "修改密码和昵称")
    @PostMapping("updateUser")
    public Result updatePasswordAndName(String token, String username, String password) throws IOException {

        Long userCode = Long.valueOf(JwtUtil.parseValueWithoutException(token, "token"));
        User user = userService.getById(userCode);

        user.setUsername(username);

        if (password.length() >= 32){
            user.setPassword(password);
        }else {
            user.setPassword(Md5Util.encode(password));
        }
        userService.updateById(user);
        return Result.successResult("ok");
    }

    /**
     * 获取登录者信息
     *
     * @param token 用户登录凭证
     * @return 返回当前登录用户信息
     */
    @ApiOperation("获取登录者信息")
    @RequestMapping("/getLoginUser")
    public Result<User> getLoginUser(String token) {
        Long userCode = Long.valueOf(JwtUtil.parseValueWithoutException(token, "token"));
        User user = userService.getById(userCode);
        return Result.successResult(user);
    }

    /**
     * 对密码进行加密处理
     *
     * @param pass 待加密的密码
     * @return 返回加密后的密码和原密码对比是否一致
     */
    @RequestMapping("/password")
    public Result<String> password(String pass) {
        return Result.successResult(Md5Util.encode(pass));
    }

    /**
     * 发送登录验证码
     *
     * @param phoneNumber 手机号码
     * @return 返回发送结果
     */
    @RequestMapping("/sendForgetPasswordCode")
    public Result<String> sendForgetPasswordCode(String phoneNumber) {
        //生成验证码
        String code = MyUtil.randomNum(4);
        Map<String, String> infoMap = new HashMap<>();
        infoMap.put("phone", phoneNumber);
        infoMap.put("code", code);
        //发送短信息
        rabbitTemplate.convertAndSend("sendCodeExchange", "sendForgetPasswordCode", infoMap);
        //redis存储验证码5分钟有效期
        stringRedisTemplate.opsForValue().set(phoneNumber + "forgetPasswordCode", code, 5, TimeUnit.MINUTES);
        return Result.successResult("短息发送成功");
    }

    @ApiOperation(value = "根据手机号修改密码")
    @PostMapping("updatePasswordByPhoneNumber")
    public Result<String> updatePasswordByPhoneNumber(String phoneNumber, String captcha) {

        String validateCode = stringRedisTemplate.opsForValue().get(phoneNumber + "forgetPasswordCode");
        if (validateCode == null || "".equals(validateCode)) return Result.failResult("验证码已失效，请重新发送！");
        if (!captcha.equals(validateCode)) return Result.failResult("验证码错误！");
        String phoneLastFour = phoneNumber.substring(phoneNumber.length() - 4);

        String password = "Wn" + MyUtil.randomNum(4) + phoneLastFour;

        User user = userService.getOne(new QueryWrapper<User>().eq("phone_number", phoneNumber));

        user.setPassword(Md5Util.encode(password));
        userService.updateById(user);
        return Result.successResult(password);
    }

    @GetMapping("/getSortList")
    public Result<Object> getSortList() {
        Page<User> page = new Page<>(1, 10);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("total_score");
        Page<User> userPage = userService.page(page, queryWrapper);
        return Result.successResult(userPage);
    }

}

